/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.freedoit.util;

import com.google.gson.Gson;
import java.util.LinkedList;
import java.util.List;
import org.freedoit.FreeDoitConfig;
import org.freedoit.common.data.FreeDoitReceiveRequest;
import org.freedoit.common.data.FreeDoitSendReceiveRequest;
import org.freedoit.common.data.FreeDoitSendReceiveResponse;
import org.freedoit.common.data.FreeDoitSendRequest;
import org.freedoit.common.data.FreeDoitSyncDataResponse;
import org.freedoit.common.shared.SharedProject;
import org.freedoit.common.shared.SharedTask;
import org.freedoit.common.util.FreeDoitDataUtils;
import org.freedoit.dao.DAOFactory;
import org.freedoit.om.Project;
import org.freedoit.om.Task;

/**
 *
 * @author wanglei
 */
public class SyncService {
    
    /**
     * This will collect local data which is not synchronized
     * and push them to the remote server
     * @return 
     */
    public static boolean execSendService(SyncServiceCallBack callBack) {
        List<Task> taskList = DAOFactory.getTaskDAO().getUnsynchronizedTaskList();
        if (taskList != null && !taskList.isEmpty()) {
            List<SharedTask> sharedTaskList = new LinkedList<SharedTask>();
            for (Task task : taskList) {
                sharedTaskList.add(Utils.toSharedData(task));
            }
            
            FreeDoitSendRequest fdsr = new FreeDoitSendRequest();
            fdsr.setTasks(sharedTaskList);
            
            
            // prepare json request data
            Gson retGson = FreeDoitDataUtils.createStandardJson();
            String message = retGson.toJson(fdsr,  new com.google.gson.reflect.TypeToken<FreeDoitSendRequest>() {  
                        }.getType());

            System.out.println(message);

            callBack.before();
            String responseBody = Utils.sendHttpPostMessage(message, FreeDoitConfig.SEND_TASK_SERVICE);

            // parse response
            if (responseBody == null) {
                // callback
                if (callBack != null) {
                    callBack.after(false);
                }
                return false;
            } else {
                System.out.println(responseBody);
                FreeDoitSyncDataResponse result = retGson.fromJson(responseBody, 
                        new com.google.gson.reflect.TypeToken<FreeDoitSyncDataResponse>() {  
                            }.getType());

                if (result.getCode() == FreeDoitSyncDataResponse.CODE_OK) {
                    // Update local task object
                    List<SharedTask> sharedTaskListResp = result.getTasks();
                    if (sharedTaskListResp != null && !sharedTaskListResp.isEmpty()) {
                        for (SharedTask task : sharedTaskListResp) {
                            DAOFactory.getTaskDAO().updateTaskSynced(task.getSerialNo(), 
                                    task.getTaskId(), result.getTimestamp());
                        }
                        
                        // callback
                        if (callBack != null) {
                            callBack.after(true);
                        }
                        return true;
                    } else {
                        // callback
                        if (callBack != null) {
                            callBack.after(false);
                        }
                        return false;
                    }
                    
                } else {
                    System.out.println("Code: " + result.getCode());
                    // callback
                    if (callBack != null) {
                        callBack.after(false);
                    }
                    return false;
                }
            }
        } else {
            if (callBack != null) {
                callBack.after(true);
            }
            return true;
        }
    }
    
    
    
    /**
     * This will collect local data which is not synchronized
     * and push them to the remote server
     * @return 
     */
    public static boolean execReceiveService(SyncServiceCallBack callBack) {
        Long timestampKey = DAOFactory.getSyncKeyDAO().getKey();
        if (timestampKey == null) {
            timestampKey = FreeDoitDataUtils.NO_TIMESTAMP_KEY;
        }
        FreeDoitReceiveRequest fdrr = new FreeDoitReceiveRequest(timestampKey);
            
        // prepare json request data
        Gson retGson = FreeDoitDataUtils.createStandardJson();
        String message = retGson.toJson(fdrr,  new com.google.gson.reflect.TypeToken<FreeDoitReceiveRequest>() {  
                    }.getType());

        System.out.println(message);

        callBack.before();
        String responseBody = Utils.sendHttpPostMessage(message, FreeDoitConfig.RECEIVE_TASK_SERVICE);

        // parse response
        if (responseBody == null) {
            // callback
            if (callBack != null) {
                callBack.after(false);
            }
            return false;
        } else {
            System.out.println(responseBody);
            FreeDoitSyncDataResponse result = retGson.fromJson(responseBody, 
                    new com.google.gson.reflect.TypeToken<FreeDoitSyncDataResponse>() {  
                        }.getType());

            if (result.getCode() == FreeDoitSyncDataResponse.CODE_OK) {
                // Update local task object
                List<SharedTask> sharedTaskListResp = result.getTasks();
                if (sharedTaskListResp != null && !sharedTaskListResp.isEmpty()) {
                    Task task = null;
                    
                    // Update Task Received
                    for (SharedTask sharedTask : sharedTaskListResp) {
                        task = Utils.fromSharedData(sharedTask);
                        task.setLastModifyTime(result.getTimestamp());
                        task.setSynced(true);
                        DAOFactory.getTaskDAO().saveOrUpdate(task);
                    }
                }
                // Update local project object
                List<SharedProject> sharedProjectListResp = result.getProjects();
                if (sharedProjectListResp != null && !sharedProjectListResp.isEmpty()) {
                    Project project = null;
                    
                    // Update Task Received
                    for (SharedProject sharedProject : sharedProjectListResp) {
                        project = new Project(sharedProject.getProjectId(), sharedProject.getProjectName(),
                                sharedProject.getComment(), sharedProject.getCreateDate(), sharedProject.getStartDate(),
                                sharedProject.getDueDate(), result.getTimestamp(), sharedProject.getStatus());

                        project.setSynced(true);
                        
                        DAOFactory.getProjectDAO().saveOrUpdate(project);
                        //DAOFactory.getTaskDAO().update(task);
                    }
                }
                // Update local task type object
//                List<SharedTaskType> sharedTaskTypeListResp = result.getTaskTypes();
//                if (sharedTaskTypeListResp != null && !sharedTaskTypeListResp.isEmpty()) {
//                    TaskType taskType = null;
//                    
//                    // Update Task Received
//                    for (SharedTaskType sharedTaskType : sharedTaskTypeListResp) {
//                        taskType = new TaskType(sharedTaskType.getTaskTypeId(), sharedTaskType.getTaskTypeName(),
//                                sharedTaskType.getTaskTypeDescrition(), sharedTaskType.getStatus(), result.getTimestamp());
//                        taskType.setLastModifyTime(result.getTimestamp());
//                        DAOFactory.getTaskTypeDAO().persist(taskType);
//                    }
//                }
                    
                // Update local synchronize key
                DAOFactory.getSyncKeyDAO().setKey(result.getTimestamp());

                // callback
                if (callBack != null) {
                    callBack.after(true);
                }
                return true;

            } else {
                System.out.println("Code: " + result.getCode());
                // callback
                if (callBack != null) {
                    callBack.after(false);
                }
                return false;
            }
        }
    }
    public static int execSendReceiveService(SyncServiceCallBack callBack) {
        Long timestampKey = DAOFactory.getSyncKeyDAO().getKey();
        if (timestampKey == null) {
            timestampKey = FreeDoitDataUtils.NO_TIMESTAMP_KEY;
        }
        FreeDoitSendReceiveRequest fdsrr = new FreeDoitSendReceiveRequest(timestampKey);
        List<Task> taskList = DAOFactory.getTaskDAO().getUnsynchronizedTaskList();
        if (taskList != null && !taskList.isEmpty()) {
            List<SharedTask> sharedTaskList = new LinkedList<SharedTask>();
            for (Task task : taskList) {
                sharedTaskList.add(Utils.toSharedData(task));
            }        
          
            fdsrr.setTasks(sharedTaskList);
        }

        // prepare json request data
        Gson retGson = FreeDoitDataUtils.createStandardJson();
        String message = retGson.toJson(fdsrr,  new com.google.gson.reflect.TypeToken<FreeDoitSendReceiveRequest>() {  
                    }.getType());

        System.out.println(message);

        callBack.before();
        String responseBody = Utils.sendHttpPostMessage(message, FreeDoitConfig.SEND_RECEIVE_TASK_SERVICE);

        // parse response
        if (responseBody == null) {
            // callback
            if (callBack != null) {
                callBack.after(false);
            }
            return Constants.FAILURE;
        } else {
            System.out.println(responseBody);
            FreeDoitSendReceiveResponse result = retGson.fromJson(responseBody, 
                    new com.google.gson.reflect.TypeToken<FreeDoitSendReceiveResponse>() {  
                        }.getType());

            if (result.getCode() == FreeDoitSyncDataResponse.CODE_OK) {
                // Update local task object which is sent
                List<SharedTask> sharedTaskListResp = result.getSendTasks();
                if (sharedTaskListResp != null && !sharedTaskListResp.isEmpty()) {
                    for (SharedTask task : sharedTaskListResp) {
                        DAOFactory.getTaskDAO().updateTaskSynced(task.getSerialNo(), 
                                task.getTaskId(), result.getTimestamp());
                    }
                }

                // Update local task object
                int taskReceive = 0;
                sharedTaskListResp = result.getReceiveTasks();
                if (sharedTaskListResp != null && (taskReceive = sharedTaskListResp.size()) > 0) {
                    Task task = null;

                    // Update Task Received
                    for (SharedTask sharedTask : sharedTaskListResp) {
                        task = Utils.fromSharedData(sharedTask);
                        task.setLastModifyTime(result.getTimestamp());
                        task.setSynced(true);
                        DAOFactory.getTaskDAO().saveOrUpdate(task);
                    }
                }
                // Update local project object
                List<SharedProject> sharedProjectListResp = result.getReceiveProjects();
                if (sharedProjectListResp != null && !sharedProjectListResp.isEmpty()) {
                    Project project = null;

                    // Update Task Received
                    for (SharedProject sharedProject : sharedProjectListResp) {
                        project = new Project(sharedProject.getProjectId(), sharedProject.getProjectName(),
                                sharedProject.getComment(), sharedProject.getCreateDate(), sharedProject.getStartDate(),
                                sharedProject.getDueDate(), result.getTimestamp(), sharedProject.getStatus());

                        project.setSynced(true);

                        DAOFactory.getProjectDAO().saveOrUpdate(project);
                        //DAOFactory.getTaskDAO().update(task);
                    }
                }
                // Update local task type object
//                List<SharedTaskType> sharedTaskTypeListResp = result.getReceiveTaskTypes();
//                if (sharedTaskTypeListResp != null && !sharedTaskTypeListResp.isEmpty()) {
//                    TaskType taskType = null;
//
//                    // Update Task Received
//                    for (SharedTaskType sharedTaskType : sharedTaskTypeListResp) {
//                        taskType = new TaskType(sharedTaskType.getTaskTypeId(), sharedTaskType.getTaskTypeName(),
//                                sharedTaskType.getTaskTypeDescrition(), sharedTaskType.getStatus(), result.getTimestamp());
//                        taskType.setLastModifyTime(result.getTimestamp());
//                        DAOFactory.getTaskTypeDAO().persist(taskType);
//                    }
//                }

                // Update local synchronize key
                DAOFactory.getSyncKeyDAO().setKey(result.getTimestamp());
                
                System.out.println(DAOFactory.getSyncKeyDAO().getKey());

                // callback
                if (callBack != null) {
                    callBack.after(true);
                }
                return taskReceive;

            } else {
                System.out.println("Code: " + result.getCode());
                // callback
                if (callBack != null) {
                    callBack.after(false);
                }
                return Constants.FAILURE;
            }
        }
    }
    
}
